home *** CD-ROM | disk | FTP | other *** search
- /*
- RUN_ELF - Load and execute big endian ix86 ELF binaries
- Copyright (C) 2001-2002 Martin Blom <martin@blom.org>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <exec/resident.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
-
- #include <stdio.h>
- #include <Amielf.h>
-
- #include "run_elf86.h"
-
- // This flag is called RTF_PPC in MorphOS.
- #define RTF_NATIVE (1<<3)
-
- #ifndef FUNCARRAY_32BIT_NATIVE
- #define FUNCARRAY_32BIT_NATIVE 0xfffefffe
- #endif
-
- #include <CompilerSpecific.h>
-
- #include "elfloader.h"
-
- #define bswap_long(x) \
- ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
- (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
-
- //#define DEBUG
-
- #define VERSION 1
- #define REVISION 7
- #define VSTRING "1.7 (13.11.2002)"
-
- const char vstr[] = "$VER: run_elf " VSTRING "\r\n";
-
- struct Library* _amithlon = NULL;
-
- void* Regs = NULL;
-
- /*** SegTracker stuff ********************************************************/
-
- typedef char* ASMCALL
- SegTrack( REG( a0, ULONG Address ),
- REG( a1, ULONG* SegNum ),
- REG( a2, ULONG* Offset ) );
-
- struct SegSem
- {
- struct SignalSemaphore seg_Semaphore;
- SegTrack* seg_Find;
- };
-
- /*** Identification semaphore ************************************************/
-
- struct RunELF86
- {
- struct SignalSemaphore Semaphore;
- UWORD Version;
- UWORD Revision;
- };
-
- /*** Stuff that should really have been in a link library ********************/
-
- static UWORD rawputchar_m68k[] __attribute__ ((aligned (4))) =
- {
- 0x2C4B, // MOVEA.L A3,A6
- 0x4EAE, 0xFDFC, // JSR -$0204(A6)
- 0x4E75 // RTS
- };
-
- void
- KPrintFArgs( UBYTE* fmt,
- ULONG* args )
- {
- RawDoFmt( fmt, args, (void(*)(void)) rawputchar_m68k, SysBase );
- }
-
- #define KPrintF( fmt, ... ) \
- ({ \
- ULONG _args[] = { __VA_ARGS__ }; \
- KPrintFArgs( (fmt), _args ); \
- })
-
-
- /*** Display a requester *****************************************************/
-
- void
- ReqA( const char* text, APTR args )
- {
- struct EasyStruct es =
- {
- sizeof (struct EasyStruct),
- 0,
- (STRPTR) "run_elf",
- (STRPTR) text,
- "OK"
- };
-
- EasyRequestArgs( NULL, &es, NULL, args );
- }
-
- #define Req( fmt, ... ) \
- ({ \
- ULONG _args[] = { __VA_ARGS__ }; \
- ReqA( (fmt), _args ); \
- })
-
- /*** A couple of native x86 functiond ****************************************/
-
- typedef APTR ASMCALL
- CallNativeInitFunction_proto( REG( d0, struct Library* library ),
- REG( d1, BPTR segList ),
- REG( d2, struct ExecBase* execbase),
- REG( a0, APTR init ) );
-
- typedef struct GuardContext* ASMCALL
- GuardEnable_proto( void );
-
- typedef void ASMCALL
- GuardDisable_proto( REG( d0, struct GuardContext* ) );
-
- CallNativeInitFunction_proto* CallNativeInitFunction = NULL;
- GuardEnable_proto* GuardEnable = NULL;
- GuardDisable_proto* GuardDisable = NULL;
-
-
- /*** Autoinit funtion definitions ********************************************/
-
- typedef APTR ASMCALL
- InitFunction_proto( REG( d0, struct Library* library ),
- REG( a0, BPTR segList ),
- REG( a6, struct ExecBase* execbase) );
-
- /*** exec.library patch definitions ******************************************/
-
- #define _LVOMakeLibrary (-84)
- #define _LVOMakeFunctions (-90)
- #define _LVOInitResident (-102)
-
- ULONG ASMCALL
- MyMakeFunctions( REG( a0, APTR target ),
- REG( a1, APTR functionArray ),
- REG( a2, APTR funcDispBase ) );
-
- struct Library* ASMCALL
- MyMakeLibrary( REG( a0, APTR vectors ),
- REG( a1, APTR structure ),
- REG( a2, APTR init ),
- REG( d0, ULONG dSize ),
- REG( d1, BPTR segList ) );
-
- APTR ASMCALL
- MyInitResident( REG( a1, struct Resident* resident ),
- REG( d1, ULONG segList ) );
-
-
- typedef ULONG ASMCALL
- MakeFunctions_proto( REG( a0, APTR target ),
- REG( a1, APTR functionArray ),
- REG( a2, APTR funcDispBase ) );
-
- typedef struct Library* ASMCALL
- MakeLibrary_proto( REG( a0, APTR vectors ),
- REG( a1, APTR structure ),
- REG( a2, APTR init ),
- REG( d0, ULONG dSize ),
- REG( d1, BPTR segList ) );
-
- typedef APTR ASMCALL
- InitResident_proto( REG( a1, struct Resident* resident ),
- REG( d1, ULONG segList ) );
-
-
- MakeFunctions_proto* OldMakeFunctions = NULL;
- MakeLibrary_proto* OldMakeLibrary = NULL;
- InitResident_proto* OldInitResident = NULL;
-
-
- /*** dos.library patch definitions *******************************************/
-
- #define _LVOLoadSeg (-150)
- #define _LVOInternalLoadSeg (-756)
- #define _LVONewLoadSeg (-768)
-
-
- BPTR ASMCALL
- MyInternalLoadSeg( REG( d0, BPTR fh ),
- REG( a0, BPTR table ),
- REG( a1, LONG* functionarray ),
- REG( a2, LONG* stack ) );
-
- BPTR ASMCALL
- MyLoadSeg( REG( d1, STRPTR name ) );
-
- BPTR ASMCALL
- MyNewLoadSeg( REG( d1, STRPTR name ),
- REG( d2, struct TagItem* tags ) );
-
-
- typedef BPTR ASMCALL
- InternalLoadSeg_proto( REG( d0, BPTR fh ),
- REG( a0, BPTR table ),
- REG( a1, LONG* functionarray ),
- REG( a2, LONG* stack ) );
-
- typedef BPTR ASMCALL
- LoadSeg_proto( REG( d1, STRPTR name ) );
-
-
- typedef BPTR ASMCALL
- NewLoadSeg_proto( REG( d1, STRPTR name ),
- REG( d2, struct TagItem* tags ) );
-
-
- InternalLoadSeg_proto* OldInternalLoadSeg = NULL;
- LoadSeg_proto* OldLoadSeg = NULL;
- NewLoadSeg_proto* OldNewLoadSeg = NULL;
-
-
- /*** misc support code *******************************************************/
-
- static struct ELFDynSymbols SymTab[] =
- {
- { "_CallFunc68k", NULL },
- { "_CallLib68k", NULL },
- { NULL, NULL }
- };
-
- static BPTR
- LoadELFSeg( STRPTR name,
- struct TagItem* tags )
- {
- BPTR s = NULL;
- void* o = NULL;
-
- (void) tags; // Remove warning
-
- o = ELFLoadObject( name, &s, SymTab );
-
- if( o == NULL || s == NULL )
- {
- s = NULL;
- }
- else
- {
- CacheClearU();
- }
-
- ELFUnLoadObject( o );
-
- return s;
- }
-
-
- void __chkabort(void)
- {
- // Disable it, just in case
- }
-
-
- static struct Node*
- FindNode( struct List* list,
- struct Node* node )
- {
- struct Node* currentnode;
-
- for( currentnode = list->lh_Head;
- currentnode->ln_Succ != NULL;
- currentnode = currentnode->ln_Succ )
- {
- if( currentnode == node )
- {
- return currentnode;
- }
- }
-
- return NULL;
- }
-
-
- static void
- ShowHit( struct Hit* hit )
- {
- int i;
-
- KPrintF( "\nILLEGAL %s %s %08lx %s %08lx (TCB: %08lx)\n",
- (ULONG) (hit->cpu == CPU_M68K ? "M68K" : "IX86"),
- (ULONG) (hit->mode == MODE_READ ? "READ from" : "WRITE to"),
- (ULONG) hit->addr,
- (ULONG) (hit->cpu == CPU_M68K ? "near" : "at" ),
- hit->pc,
- (ULONG) hit->task );
-
-
- if( hit->cpu == CPU_IX86 )
- {
- KPrintF( "EFLAGS: %08lx\n", hit->c.ix86.eflags );
- KPrintF( " EAX EBX ECX EDX"
- " ESI EDI ESP EBP\n" );
- KPrintF( "Regs: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- hit->c.ix86.eax, hit->c.ix86.ebx, hit->c.ix86.ecx, hit->c.ix86.edx,
- hit->c.ix86.esi, hit->c.ix86.edi, hit->c.ix86.esp, hit->c.ix86.ebp );
-
- KPrintF( "Stck:" );
-
- for( i = 0; i < 8; ++i )
- {
- KPrintF( " %08lx", bswap_long( hit->stack[ i ] ) );
- }
-
- KPrintF( "\n " );
-
- for( i = 8; i < 16; ++i )
- {
- KPrintF( " %08lx", bswap_long( hit->stack[ i ] ) );
- }
-
- KPrintF( "\nStck:" );
-
- for( i = 0; i < 8; ++i )
- {
- KPrintF( " %08lx", hit->stack[ i ] );
- }
-
- KPrintF( "\n[BE] " );
-
- for( i = 8; i < 16; ++i )
- {
- KPrintF( " %08lx", hit->stack[ i ] );
- }
- }
- else
- {
- KPrintF( "SR:%04lx\n", hit->c.m68k.sr );
- KPrintF( "Data:" );
-
- for( i = 0; i < 8; ++i )
- {
- KPrintF( " %08lx", hit->c.m68k.dregs[ i ] );
- }
-
- KPrintF( "\nAddr:" );
-
- for( i = 0; i < 8; ++i )
- {
- KPrintF( " %08lx", hit->c.m68k.aregs[ i ] );
- }
-
- KPrintF( "\nStck:" );
-
- for( i = 0; i < 8; ++i )
- {
- KPrintF( " %08lx", hit->stack[ i ] );
- }
-
- KPrintF( "\n " );
-
- for( i = 8; i < 16; ++i )
- {
- KPrintF( " %08lx", hit->stack[ i ] );
- }
- }
-
- KPrintF( "\n%s", (ULONG) hit->disasm );
-
- Forbid();
-
- {
- struct SegSem* seg_sem;
- ULONG seg_num = 0;
- ULONG offset = 0;
- char* file_name = NULL;
-
- seg_sem = (struct SegSem*) FindSemaphore( "SegTracker" );
-
- if( seg_sem != NULL )
- {
- if( seg_sem->seg_Find != NULL )
- {
- file_name = seg_sem->seg_Find( hit->pc, &seg_num, &offset );
-
- if( file_name != NULL )
- {
- KPrintF( "----> %08lx - \"%s\" Hunk %04lx Offset %08lx\n",
- hit->pc, (ULONG) file_name, seg_num, offset );
- }
- }
- }
-
- // See if the task is still around
-
- if( FindNode( &SysBase->TaskReady, (struct Node*) hit->task ) != NULL ||
- FindNode( &SysBase->TaskWait, (struct Node*) hit->task ) != NULL )
- {
- struct Process* proc = (struct Process*) hit->task;
-
- KPrintF( "Name: \"%s\"", (ULONG) proc->pr_Task.tc_Node.ln_Name );
-
- if( proc->pr_Task.tc_Node.ln_Type == NT_PROCESS &&
- proc->pr_TaskNum != 0 )
- {
- struct CommandLineInterface* cli = BADDR( proc->pr_CLI );
-
- if( cli->cli_Module != NULL )
- {
- KPrintF( " CLI: \"%b\"", cli->cli_CommandName );
- }
-
- if( file_name != NULL )
- {
- KPrintF( " Hunk %04lx Offset %08lx\n",
- seg_num, offset );
-
- }
- }
-
- KPrintF( "\n" );
- }
- }
-
- Permit();
-
- }
-
-
-
- /*** main() ******************************************************************/
-
- int
- main( void )
- {
- int rc = 0;
-
- if( sizeof( struct Hit ) != 1024 )
- {
- Printf( "sizeof( struct Hit ) == %ld\n", sizeof( struct Hit ) );
- return 20;
- }
-
- _amithlon = OpenResource( "amithlon.resource" );
-
- // if( _amithlon == NULL )
- // {
- // _amithlon = OpenResource( "amithlon.resource" );
- // }
-
- if( _amithlon == NULL )
- {
- Printf( "This program is for Amithlon only.\n" );
- rc = 20;
- }
- else
- {
- void* run_elf86;
-
- run_elf86 = open_elf( "PROGDIR:run_elf86" );
-
- if( run_elf86 == NULL )
- {
- Printf( "Unable to load ix86 native functions from 'run_elf86'.\n" );
- rc = 20;
- }
- else
- {
- struct ELFDynSymbols* stab = SymTab;
-
- // Get the emulations register storage address
-
- Regs = find_symbol( NULL, "regs" );
-
- if( Regs == NULL )
- {
- Printf( "Unable to find symbol 'regs'.\n" );
- rc = 20;
- }
-
- // Load symbols from 'run_elf86'
-
- CallNativeInitFunction = (CallNativeInitFunction_proto*)
- find_slowcall( run_elf86, "CallNativeInitFunction" );
-
- GuardEnable = (GuardEnable_proto*)
- find_slowcall( run_elf86, "GuardEnable" );
-
- GuardDisable = (GuardDisable_proto*)
- find_slowcall( run_elf86, "GuardDisable" );
-
- if( CallNativeInitFunction == NULL )
- {
- Printf( "Unable to find symbol 'CallNativeInitFunction'.\n" );
- rc = 20;
- }
-
- if( GuardEnable == NULL )
- {
- Printf( "Unable to find symbol 'GuardEnable'.\n" );
- rc = 20;
- }
-
- if( GuardDisable == NULL )
- {
- Printf( "Unable to find symbol 'GuardDisable'.\n" );
- rc = 20;
- }
-
- // Load all symbols that will be resolved by the ELF loader
-
- while( stab->name != NULL )
- {
- stab->addr = find_symbol( run_elf86, stab->name );
-
- if( stab->addr == NULL )
- {
- Printf( "Unable to find symbol '%s'.\n",
- (ULONG) stab->name );
- rc = 20;
- }
-
- ++stab;
- }
-
- if( rc == 0 )
- {
- struct RDArgs* ra = NULL;
- struct
- {
- STRPTR file;
- ULONG guard;
- ULONG patch;
- STRPTR args;
- } args = { NULL, FALSE, FALSE, "" };
-
- ra = ReadArgs( "FILE,GUARD/S,PATCH/S,ARGS/F", (ULONG*) &args, NULL );
-
- if( ra == NULL ||
- ( args.file == NULL && ! args.patch) ||
- ( args.file != NULL && args.patch ) )
- {
- Printf( "Usage: run_elf [GUARD] <program> [<arguments>]\n" );
- Printf( " or: run_elf [GUARD] PATCH\n" );
- rc = 20;
- }
- else
- {
- struct GuardContext* guard_context = NULL;
-
- if( args.guard )
- {
- guard_context = GuardEnable();
-
- if( guard_context == NULL )
- {
- Printf( "Unable to install guard.\n" );
- }
- }
-
- if( args.patch )
- {
- struct MsgPort* setman;
- struct RunELF86* semaphore;
-
- semaphore = AllocVec( sizeof( *semaphore),
- MEMF_PUBLIC | MEMF_CLEAR );
-
- if( semaphore != NULL )
- {
- semaphore->Semaphore.ss_Link.ln_Name = "RunELF86";
- semaphore->Semaphore.ss_Link.ln_Pri = -127;
- semaphore->Version = VERSION;
- semaphore->Revision = REVISION;
- }
-
- // Avoid race conditions when patching:
- Forbid();
-
- // Ah, I just love SetFunction(). Don't you agree, Frieden?
- // SCNR ... :-)
-
- OldMakeFunctions = (MakeFunctions_proto*)
- SetFunction( (struct Library*) SysBase,
- _LVOMakeFunctions,
- (ULONG (*)(void)) MyMakeFunctions );
-
- OldMakeLibrary = (MakeLibrary_proto*)
- SetFunction( (struct Library*) SysBase,
- _LVOMakeLibrary,
- (ULONG (*)(void)) MyMakeLibrary );
-
- OldInitResident = (InitResident_proto*)
- SetFunction( (struct Library*) SysBase,
- _LVOInitResident,
- (ULONG (*)(void)) MyInitResident );
-
- // OldInternalLoadSeg = (InternalLoadSeg_proto*)
- // SetFunction( (struct Library*) DOSBase,
- // _LVOInternalLoadSeg,
- // (ULONG (*)(void)) MyInternalLoadSeg );
-
- OldLoadSeg = (LoadSeg_proto*)
- SetFunction( (struct Library*) DOSBase,
- _LVOLoadSeg,
- (ULONG (*)(void)) MyLoadSeg );
-
- OldNewLoadSeg = (NewLoadSeg_proto*)
- SetFunction( (struct Library*) DOSBase,
- _LVONewLoadSeg,
- (ULONG (*)(void)) MyNewLoadSeg );
-
- if( semaphore != NULL )
- {
- AddSemaphore( &semaphore->Semaphore );
- }
-
- setman = FindPort( "SetMan" );
-
- while( TRUE )
- {
- ULONG signals;
-
- // Temporary break the Forbid() state
- Delay( 1 );
-
- signals = SetSignal( 0,
- SIGBREAKF_CTRL_C |
- SIGBREAKF_CTRL_E |
- SIGBREAKF_CTRL_F );
-
- if( signals & SIGBREAKF_CTRL_C )
- {
- if( setman != NULL )
- {
- break;
- }
- else
- {
- Printf( "Can't terminate since PatchControl is not running.\n" );
- }
- }
-
- if( signals & SIGBREAKF_CTRL_E )
- {
- if( guard_context == NULL )
- {
- guard_context = GuardEnable();
-
- if( guard_context != NULL )
- {
- Printf( "Guard installed.\n" );
- }
- else
- {
- Printf( "Unable to install guard.\n" );
- }
- }
- else
- {
- Printf( "Guard already installed.\n" );
- }
- }
-
- if( signals & SIGBREAKF_CTRL_F )
- {
- if( guard_context != NULL )
- {
- GuardDisable( guard_context );
- guard_context = NULL;
- Printf( "Guard removed.\n" );
- }
- else
- {
- Printf( "Guard already removed.\n" );
- }
- }
-
- if( guard_context != NULL )
- {
- while( guard_context->read_index != guard_context->write_index )
- {
- ShowHit( &guard_context->hits[ guard_context->read_index ] );
-
- ++guard_context->read_index;
- }
- }
-
- }
-
- if( semaphore != NULL )
- {
- // Disables Forbid() state while waiting.
- ObtainSemaphore( &semaphore->Semaphore );
-
- // Forbid() is active again!
- ReleaseSemaphore( &semaphore->Semaphore );
- RemSemaphore( &semaphore->Semaphore );
- FreeVec( semaphore );
- }
-
- SetFunction( (struct Library*) SysBase,
- _LVOMakeFunctions,
- (ULONG (*)(void)) OldMakeFunctions );
-
- SetFunction( (struct Library*) SysBase,
- _LVOMakeLibrary,
- (ULONG (*)(void)) OldMakeLibrary );
-
- SetFunction( (struct Library*) SysBase,
- _LVOInitResident,
- (ULONG (*)(void)) OldInitResident );
-
- // SetFunction( (struct Library*) DOSBase,
- // _LVOInternalLoadSeg,
- // (ULONG (*)(void)) OldInternalLoadSeg );
-
- SetFunction( (struct Library*) DOSBase,
- _LVOLoadSeg,
- (ULONG (*)(void)) OldLoadSeg );
-
- SetFunction( (struct Library*) DOSBase,
- _LVONewLoadSeg,
- (ULONG (*)(void)) OldNewLoadSeg );
-
- Permit();
- }
- else
- {
- BPTR s = NULL;
-
- s = LoadELFSeg( args.file, NULL );
-
- if( s == 0 )
- {
- Printf( "Unable to load ELF object %s\n", (ULONG) args.file );
- rc = 20;
- }
- else
- {
- int cmdlen = strlen( args.args ) + 1;
- char* cmdline;
-
- cmdline = AllocVec( cmdlen + 1, MEMF_ANY );
-
- if( cmdline == NULL )
- {
- Printf( "Out of memory.\n" );
- rc = 20;
- }
- else
- {
- struct Task* me = FindTask( NULL );
-
- strcpy( cmdline, args.args );
- cmdline[ cmdlen - 1 ] = '\n';
- cmdline[ cmdlen ] = 0;
-
- SetProgramName( args.file );
- rc = RunCommand( s,
- me->tc_SPUpper - me->tc_SPLower,
- cmdline, cmdlen );
-
- FreeVec( cmdline );
- }
-
- UnLoadSeg( s );
- }
- }
-
- if( guard_context != NULL )
- {
- GuardDisable( guard_context );
- }
- }
-
- FreeArgs( ra );
- }
-
- close_elf( run_elf86 );
- }
- }
-
- return rc;
- }
-
-
- /*** exec.library patches follows ********************************************/
-
- static APTR
- CallInitFunc( struct Resident* resident,
- APTR init,
- struct Library* library,
- BPTR segList )
- {
- APTR res;
-
- #ifdef DEBUG
- KPrintF( "CallInitFunc( 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx )\n",
- (ULONG) resident, (ULONG) init, (ULONG) library, segList );
- #endif
-
- if( resident->rt_Flags & RTF_NATIVE )
- {
- // __asm__("illegal");
- res = CallNativeInitFunction( library, segList, SysBase, init );
- // __asm__("illegal");
- }
- else
- {
- InitFunction_proto* i = (InitFunction_proto*) init;
-
- res = i( library, segList, SysBase );
- }
-
- #ifdef DEBUG
- KPrintF( "CallInitFunc -> 0x%08lx\n", (ULONG) res );
- #endif
-
- return res;
- }
-
-
- struct EntryTrampoline
- {
- UBYTE mov;
- ULONG regs;
- UBYTE jmp;
- ULONG addr;
- UBYTE nop1;
- UBYTE nop2;
- } __attribute__((packed));
-
-
- #define SET_ENTRYTRAMPOLINE(tp,funcptr) \
- ((struct EntryTrampoline*) tp)->mov = 0xb8; \
- ((struct EntryTrampoline*) tp)->regs = bswap_long( (ULONG) Regs ); \
- ((struct EntryTrampoline*) tp)->jmp = 0xe9; \
- ((struct EntryTrampoline*) tp)->addr = bswap_long( (ULONG) (funcptr) - \
- 10 - (ULONG) (tp) );\
- ((struct EntryTrampoline*) tp)->nop1 = 0x90; \
- ((struct EntryTrampoline*) tp)->nop2 = 0x90;
-
- struct JumpVec
- {
- unsigned short jmp;
- unsigned char vec[4];
- };
-
- #define __AROS_ASMJMP 0x4EF9
- #define __AROS_SET_VEC(v,a) (*(ULONG*)(v)->vec=(ULONG)(a))
- #define __AROS_GET_VEC(v) ((APTR)(*(ULONG*)(v)->vec))
- #define __AROS_GETJUMPVEC(lib,n) ((struct JumpVec *)(((UBYTE *)lib)-(n*LIB_VECTSIZE)))
- #define __AROS_GETVECADDR(lib,n) (__AROS_GET_VEC(__AROS_GETJUMPVEC(lib,n)))
- #define __AROS_SETVECADDR(lib,n,addr) (__AROS_SET_VEC(__AROS_GETJUMPVEC(lib,n),(APTR)(addr)))
- #define __AROS_INITVEC(lib,n) __AROS_GETJUMPVEC(lib,n)->jmp = __AROS_ASMJMP, \
- __AROS_SETVECADDR(lib,n,0)
- ULONG ASMCALL
- MyMakeFunctions( REG( a0, APTR target ),
- REG( a1, APTR functionArray ),
- REG( a2, APTR funcDispBase ) )
- {
- /* This code is from AROS, except for the FUNCARRAY_32BIT_NATIVE part. */
-
- long n;
- // APTR lastvec;
-
- #ifdef DEBUG
- KPrintF( "MyMakeFunctions( 0x%08lx, 0x%08lx, 0x%08lx )\n",
- (ULONG) target, (ULONG) functionArray, (ULONG) funcDispBase );
- #endif
-
- n = 1;
-
- if (funcDispBase!=NULL)
- {
- /* If FuncDispBase is non-NULL it's an array of relative offsets */
- WORD *fp=(WORD *)functionArray;
-
- /* -1 terminates the array */
- while(*fp!=-1)
- {
- /* Decrement vector pointer by one and install vector */
- __AROS_INITVEC(target,n);
- if (*fp)
- __AROS_SETVECADDR(target,n,funcDispBase+*fp);
-
- /* Use next array entry */
- fp++;
- n++;
- }
- }
- else
- {
- /* If FuncDispBase is NULL it's an array of function pointers */
- void **fp=(void **)functionArray;
-
- if( *fp == (void*) FUNCARRAY_32BIT_NATIVE )
- {
- struct EntryTrampoline* tp = (struct EntryTrampoline*)
- ( (ULONG) target - ((struct Library*) target)->lib_NegSize );
-
- ++fp;
-
- /* -1 terminates the array */
- while(*fp!=(void *)-1)
- {
- /* Decrement vector pointer by one and install vector */
- __AROS_INITVEC(target,n);
- if( _amithlon->lib_Version < 2 )
- {
- if (*fp)
- __AROS_SETVECADDR(target,n,(ULONG)tp|0x00000001); // "slowcall"
-
- /* Install trampoline */
- SET_ENTRYTRAMPOLINE(tp,*fp);
-
- tp++;
- }
- else
- {
- if (*fp)
- __AROS_SETVECADDR(target,n,(ULONG)*fp|0x80000001); // "bslowcall"
- }
-
-
- /* Use next array entry */
- fp++;
- n++;
- }
- }
- else
- {
- /* -1 terminates the array */
- while(*fp!=(void *)-1)
- {
- /* Decrement vector pointer by one and install vector */
- __AROS_INITVEC(target,n);
- if (*fp)
- __AROS_SETVECADDR(target,n,*fp);
-
- /* Use next array entry */
- fp++;
- n++;
- }
- }
- }
-
- n = ((struct Library*) target)->lib_NegSize;
-
- /* Clear instruction cache for the whole jumptable and trampolines */
- CacheClearE(target - n, n, CACRF_ClearI|CACRF_ClearD);
-
- #ifdef DEBUG
- KPrintF( "MyMakeFunctions -> 0x%ld\n", n );
- #endif
-
- /* Return size of jumptable */
- return n;
- }
-
- struct Library* ASMCALL
- MyMakeLibrary( REG( a0, APTR vectors ),
- REG( a1, APTR structure ),
- REG( a2, APTR init ),
- REG( d0, ULONG dSize ),
- REG( d1, BPTR segList ) )
- {
- /* This code is from AROS, except for the FUNCARRAY_32BIT_NATIVE part. */
-
- struct Library *library;
- ULONG negsize=0;
-
- #ifdef DEBUG
- KPrintF( "MyMakeLibrary( 0x%08lx, 0x%08lx, 0x%08lx, %ld, %08lx )\n",
- (ULONG) vectors, (ULONG) structure, (ULONG) init, dSize,
- (ULONG) segList );
- #endif
-
- /* Calculate the jumptable's size */
- if(*(WORD *)vectors==-1)
- {
- /* Count offsets */
- WORD *fp=(WORD *)vectors+1;
- while(*fp++!=-1)
- negsize+=LIB_VECTSIZE;
- }
- else
- {
- /* Count function pointers */
- void **fp=(void **)vectors;
-
- if( *fp == (void*) FUNCARRAY_32BIT_NATIVE )
- {
- fp++;
-
- while( *fp != (void *) -1 )
- {
- negsize += LIB_VECTSIZE;
- if( _amithlon->lib_Version < 2 )
- {
- negsize += sizeof( struct EntryTrampoline );
- }
- ++fp;
- }
- }
- else
- {
- while(*fp++!=(void *)-1)
- negsize+=LIB_VECTSIZE;
- }
- }
-
- /* Align library base */
- negsize=(negsize+3)&~3;
-
- /* Allocate memory */
- library=(struct Library *)AllocMem(dSize+negsize,MEMF_PUBLIC|MEMF_CLEAR);
-
- /* And initilize the library */
- if(library!=NULL)
- {
- /* Get real library base */
- library=(struct Library *)((char *)library+negsize);
-
- /* Write sizes *before* MakeFunctions!! */
- library->lib_NegSize=negsize;
- library->lib_PosSize=dSize;
-
- /* Build jumptable */
- if(*(WORD *)vectors==-1)
- /* offsets */
- MakeFunctions(library,(WORD *)vectors+1,(ULONG)vectors);
- else
- /* function pointers */
- MakeFunctions(library,vectors,NULL);
-
- /* Create structure */
- if(structure!=NULL)
- InitStruct(structure,library,0);
-
- /* Call init vector */
- if(init!=NULL)
- {
- InitFunction_proto* i = (InitFunction_proto*) init;
-
- library = i( library, segList, SysBase );
- }
- }
-
- #ifdef DEBUG
- KPrintF( "MyMakeLibrary -> 0x%08lx\n", (ULONG) library );
- #endif
-
- /* All done */
- return library;
- }
-
- APTR ASMCALL
- MyInitResident( REG( a1, struct Resident* resident ),
- REG( d1, ULONG segList ) )
- {
- APTR res = NULL;
- /* This code is from AROS, except for the RTF_NATIVE part. */
-
- #ifdef DEBUG
- KPrintF( "MyInitResident( 0x%08lx, 0x%08lx )\n",
- (ULONG) resident, segList );
- #endif
-
- /* Check for validity */
- if(resident->rt_MatchWord != RTC_MATCHWORD ||
- resident->rt_MatchTag != resident)
- goto end;
-
- /* Depending on the autoinit flag... */
- if(resident->rt_Flags & RTF_AUTOINIT)
- {
- /* ...initialize automatically... */
- struct init
- {
- ULONG dSize;
- APTR vectors;
- APTR structure;
- APTR init;
- };
- struct init *init = (struct init *)resident->rt_Init;
- struct Library *library;
-
- /*
- Make the library. Don't call the Init routine yet, but delay
- that until we can copy stuff from the tag to the libbase.
- */
- library = MakeLibrary(init->vectors, init->structure,
- NULL, init->dSize, segList);
-
- if(library != NULL)
- {
- /*
- Copy over the interesting stuff from the ROMtag, and set the
- library state to indicate that this lib has changed and
- should be checksummed at the next opportunity.
-
- Don't copy the priority, because a tag's priority doesn't
- mean the same as a lib's priority.
- */
- library->lib_Node.ln_Type = resident->rt_Type;
- library->lib_Node.ln_Name = resident->rt_Name;
- library->lib_Version = resident->rt_Version;
- library->lib_IdString = resident->rt_IdString;
- library->lib_Flags = LIBF_SUMUSED|LIBF_CHANGED;
-
- /*
- Call the library init vector, if set.
- */
- if(init->init)
- {
- library = CallInitFunc( resident, init->init, library, segList );
- }
-
- /*
- Test the library base, in case the init routine failed in
- some way.
- */
-
- if(library != NULL)
- {
- /*
- Add the initialized module to the system.
- */
- switch(resident->rt_Type)
- {
- case NT_DEVICE:
- AddDevice((struct Device *)library);
- break;
- case NT_LIBRARY:
- AddLibrary(library);
- break;
- case NT_RESOURCE:
- AddResource(library);
- break;
- }
- }
- }
-
- res = library;
- }
- else
- {
- /* ...or let the library do it. */
-
- res = CallInitFunc( resident, resident->rt_Init, NULL, segList );
- }
-
- end:
-
- #ifdef DEBUG
- KPrintF( "MyInitResident -> 0x%08lx\n", (ULONG) res );
- #endif
- return res;
- }
-
- /*** dos.library patches follows *********************************************/
-
- BPTR ASMCALL
- MyInternalLoadSeg( REG( d0, BPTR fh ),
- REG( a0, BPTR table ),
- REG( a1, LONG* functionarray ),
- REG( a2, LONG* stack ) )
- {
- #ifdef DEBUG
- KPrintF( "MyInternalLoadSeg( 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx )\n",
- fh, table, (ULONG) functionarray, (ULONG) stack );
- #endif
-
- return OldInternalLoadSeg( fh, table, functionarray, stack );
- }
-
-
- BPTR ASMCALL
- MyLoadSeg( REG( d1, STRPTR name ) )
- {
- BPTR result;
-
- #ifdef DEBUG
- KPrintF( "MyLoadSeg( %s )\n", (ULONG) name );
- #endif
-
- result = OldLoadSeg( name );
-
- if( result == 0 )
- {
- result = LoadELFSeg( name, NULL );
- }
-
- return result;
- }
-
-
- BPTR ASMCALL
- MyNewLoadSeg( REG( d1, STRPTR name ),
- REG( d2, struct TagItem* tags ) )
- {
- BPTR result;
-
- #ifdef DEBUG
- KPrintF( "MyNewLoadSeg( %s, %08lx )\n", (ULONG) name, (ULONG) tags );
- #endif
-
- result = OldNewLoadSeg( name, tags );
-
- if( result == 0 )
- {
- result = LoadELFSeg( name, tags );
- }
-
- return result;
- }
-